from common.flask_package import *
from model.car_info import *
from model.order import *
from model.vip import *
from model.place import *
from ai.plate import *
from common.my_msg import *
from common.my_fun import *
from datetime import datetime,timedelta
import json
import shutil
import os

bp_car_info = Blueprint('car_info', __name__, url_prefix='/car_info')

'''
功能:车辆信息录入
用途：后台管理系统
解释:对于未进入过该停车场的车辆,会保存其车牌号、进入时间等信息,此时我们置数据库的car_state字段为True状态表示该车处在停车场停车状态，
当再次获取到相同的车牌(表示离开停车场)时会有两个判断条件，会员和非会员，如果是会员则不需要支付金额即可离开并且记录离开时间，如果为非会员
则会根据停留的时间产生相应的金额，需要等待支付完金额后再次获取车牌（相当于再次调用该路由）经过判断money字段不为空则可离开并且记录离开时间，
此时数据库表中的car_state为False表示车辆可以离开，当再次扫描到该车牌(第二次进入)则会判断数据库中是否存在该车牌，如果存在(相当于回头客)
之前的记录不会作任何修改，而是再新增字段保存该车信息然后重复以上过程。
注：金额支付流程在其它路由
'''

# 复制文件到某个文件夹啊
def copy_img():
    src_path = ".\static\plateimg\plate.jpg"  # 替换为实际的原始图片路径
    dst_dir = "static\car_img"  # 替换为实际的目标文件夹路径
    new_name = f"{my_generate()}.jpg"  # 新的图片名称
    file_url = os.path.join(dst_dir, new_name)

    os.makedirs(dst_dir, exist_ok=True)  # 创建目标文件夹（如果不存在）
    shutil.copy(src_path, file_url)  # 复制原始图片到目标文件夹

    return file_url
# -----------------------车辆信息录入----------------------
@bp_car_info.route('/add', methods=['POST'])
def car_info_add():
    if request.method == 'POST':
        imgpath='./static/plateimg/result.jpg'
        car_number=place_str_relust(imgpath)
        stateimg=f'{my_gethost()}/static/plateimg/result.jpg'#原始图片
        plateimg=f'{my_gethost()}/static/plateimg/plate.jpg' #截取出车牌的图片
        if car_number =='无法识别': #无法识别的情况下
            data = {'code': state_error(), 'msg': '无法识别','plateimg':None}
            my_tts('无法识别') #语音
            return jsonify(data)
        # car_number = my_car_number(imgpath)  # 获取车牌号，百度api
        query = Car_info.query_car_number_first(car_number)
        place=Place.query_place_state()
        if place!=-1: #有车位
            car_img_url = f'/{copy_img()}'  # 图片路径
            if query is None:
                car_color = None  # 车辆颜色
                car_into_time = datetime.now()  # 车辆进入时间
                car_leave_time = None  # 车辆出场时间
                money = None  # 所付金额
                car_state = 'True'
                result = Car_info.add_car_info(car_number,car_img_url,car_color,car_into_time,car_leave_time
                                               ,money,car_state)
                if result == 0:
                    place_number=place[0] #车位标识
                    Place.modify_place(place_number, car_number)  # 添加车辆信息到车位
                    data = {'code': state_ok(),'msg': f'{car_number} 进场成功','stateimg':stateimg,'plateimg':plateimg}
                    my_tts(f'{car_number}进场成功')  # 语音
                else:
                    data = {'code': state_error(),'msg': f'{car_number} 进场失败','stateimg':stateimg,'plateimg':plateimg}
                    my_tts(f'{car_number}进场失败')  # 语音
            elif query.car_state == 'False' and query.car_leave_time is not None:
                car_color = None  # 车辆颜色
                car_into_time = datetime.now()  # 车辆进入时间
                car_leave_time = None  # 车辆出场时间
                money = None  # 所付金额
                car_state = 'True'
                result = Car_info.add_car_info(car_number, car_img_url,car_color, car_into_time, car_leave_time, money, car_state)
                if result == 0:
                    place_number = place[0]  # 车位标识
                    Place.modify_place(place_number, car_number)  # 添加车辆信息到车位
                    data = {'code': state_ok(),'msg': f'{car_number} 欢迎再次光临','stateimg':stateimg,'plateimg':plateimg}
                    my_tts(f'{car_number}欢迎再次光临')  # 语音
                else:
                    data = {'code': state_error(),'msg': f'{car_number} 进入失败','stateimg':stateimg,'plateimg':plateimg}
                    my_tts(f'{car_number}进入失败')  # 语音
            else:
                car_leave_time=datetime.now()
                if query.money is not None:
                    rlt = Car_info.modify_car_leave_time(car_number, car_leave_time)
                    if rlt == 0:
                        place_number = Place.query_plate_car_number(car_number)
                        Place.modify_place_number_None(place_number)  #车辆出场将车位修改车位
                        data = {'code': state_ok(),'msg': f'{car_number} 车辆出场成功','stateimg':stateimg,'plateimg':plateimg}
                        my_tts(f'{car_number}出场成功')  # 语音
                    else:
                        data = {'code': state_error(),'msg': f'{car_number} 车辆出场失败','stateimg':stateimg,'plateimg':plateimg}
                        my_tts(f'{car_number}车辆出场失败')  # 语音
                elif query.money is None:
                    rut = Vip.query_car_number_is_vip(car_number)
                    if rut == 0: #会员免付款
                        rlt = Car_info.modify_car_leave_time(car_number, car_leave_time)
                        if rlt==0:
                            place_number = Place.query_plate_car_number(car_number)
                            Place.modify_place_number_None(place_number)  # 车辆出场将车位修改车位
                            data = {'code': state_ok(),'msg': f'{car_number} 车辆出场成功','stateimg':stateimg,'plateimg':plateimg}
                            my_tts(f'{car_number}出场成功')  # 语音
                        else:
                            data = {'code': state_error(),'msg': f'{car_number} 车辆出场失败','stateimg':stateimg,'plateimg':plateimg}
                            my_tts(f'{car_number}出场失败')  # 语音
                    else:
                        data = {'code': state_warn(),'msg': '请付款','stateimg':stateimg,'plateimg':plateimg}
                        my_tts(f'{car_number}请付款')  # 语音
                else:
                    data = {'code': state_error(),'msg': '禁止出场','stateimg':stateimg,'plateimg':plateimg}
                    my_tts(f'{car_number}禁止出场')  # 语音
        else:
            data = {'code': state_warn(),'msg': '已无停车位','stateimg':stateimg,'plateimg':plateimg}
            my_tts('已无停车位')  # 语音
    return jsonify(data)

# -----------------图片上传识别-----------------------
@bp_car_info.route('/plateimg/add', methods=['POST'])
def car_info_plateimg_add():
    if request.method=='POST':
        if 'file' not in request.files:
            data = {'code': state_warn(), 'msg': '请上传文件'}
        else:
            file = request.files['file']
            if file.filename == '':
                data = {'code': state_error(), 'msg': '请上传正确的图片'}
            else:
                save_path = './static/plateimg/result.jpg'
                file.save(save_path)
                if os.path.exists(save_path):
                    data = {'code': state_ok(), 'msg': '文件保存成功'}
                else:
                    data = {'code': state_error(), 'msg': '文件保存失败'}
    return jsonify(data)


'''
功能:获取车辆全部信息
用途：后台管理系统
解释：获取前端传递的车牌号、车辆状态(True、False)参数用于模糊查询、page(分页页数这里是5条一页)，解释为何需要分页，因为
当数据足够多时(例如：1000万条)服务器如果一下全部返回会导致服务器负载大响应慢，客户端体验差，所以利用分页可是比较好的选择(原因之一)
解释模糊查询过程：首先会根据前端传递的值来判断(前后端相互沟通定制接收规范)，当car_number不为空时表明客户端需要根据车牌号来模糊查询信息，例如：
客户端传递过来一个'桂'字，数据库中car_number字段存在'桂'的那一行的信息全部被返回给客户端，相反car_state也是一样，当car_number和car_state
都为空时表明客户端没有进行搜索，只是简单地获取数据，如果page没有指定值传递过来则page默认1，返回第一页数据，也是数据库中最新的数据
'''
# -----------------------获取车辆全部信息-----------------------
@bp_car_info.route('/get', methods=['GET'])
def car_info_get():
    car_number = request.args.get('car_number')
    car_state = request.args.get('car_state')
    page = request.args.get('page', default=1)
    #''传递过来是一个字符不是空
    if car_number is not None and car_number !='':
        result = Car_info.car_number_search(car_number)
        count = 1
    elif car_state is not None and car_state != '':
        result = Car_info.car_state_search(car_state)
        count = 1
    else:
        result, count = Car_info.query_car_info_all(page)

    car_list = []
    try:
        for i in result:
            item = {
                'car_id': i.car_id,
                'car_number': i.car_number,
                'car_img_url':f'{my_gethost()}{i.car_img_url}',
                'car_color': i.car_color,
                'car_into_time': str(i.car_into_time),
                'car_leave_time': str(i.car_leave_time),
                'money': i.money,
                'car_state': i.car_state
            }
            car_list.append(item)

        data = {
            'code': state_ok(),
            'msg': '车辆信息获取成功',
            'count': count,
            'data': car_list
        }
    except Exception as e:
        data = {
            'code': state_error(),
            'msg': '车辆信息获取失败',
            'count': 1,
            'data': car_list
        }

    return Response(json.dumps(data),mimetype='application/json')

# --------------------修改车辆在库状态-------------------
@bp_car_info.route('/modify/car_state', methods=['POST'])
def car_info_modify_car_state():
    if request.method == 'POST':
      car_id=request.json.get('car_id')
      relust=Car_info.modify_car_is_state(car_id)
      if relust==0:
          data={
              'code':state_ok(),
              'msg':'修改成功'
          }
      else:
          data = {
              'code': state_error(),
              'msg': '修改失败'
          }
    return jsonify(data)

'''
功能:查车辆是否在库
用途：前台客户端,
解释:根据前端传递过来的车牌号参数(car_number) 进行数据库查询,当返回0时说明该车不为空并且在库
'''
# --------------查车辆是否在库------------------------
@bp_car_info.route('/is/bank', methods=['GET'])
def car_info_is_bank():
    car_number = request.args.get('car_number')
    iscar = Car_info.query_car_is(car_number)
    if iscar == 0:
        data = {
            'code': state_ok(),
            'msg': '车辆在库',
        }
    else:
        data = {
            'code': state_error(),
            'msg': '车辆不在库',
            'money': 0
        }
    return jsonify(data)

'''
功能:客户端前台支付金额
用途：前台客户端,
解释:GET请求：根据前端传递过来的车牌号参数(car_number)，然后调用is_money函数，返回两个值1.需要支付的金额，2.是否是会员，然后响应数据
POST请求:获取前端的车牌号以及金额，当获取到的金额与后端产生的金额匹配时修改该车牌对应的数据库字段的money保存金额，并且产生相应的订单
'''
# --------------------------------客户端前台支付金额-----------------------------
@bp_car_info.route('/pay/money', methods=['GET','POST'])
def car_info_pay_money():
    if request.method=='GET':
        car_number = request.args.get('car_number')
        money,vip=is_money(car_number)
        query=Car_info.query_car_number_first(car_number)
        vip_query=Vip.query_car_number_vip(car_number)
        if query.car_state == 'False' or (vip_query is not None and (
                vip_query.vip_month_card == 'True' or vip_query.vip_year_card == 'True')):
            data = {
                'code': state_warn(),
                'msg': '没有需要支付的金额',
                'money': 0,
                'is_vip': vip
            }
        else:
            data = {
                'code': state_ok(),
                'msg': '请支付金额',
                'money':money,
                'is_vip':vip
            }
    if request.method=='POST':
            car_number = request.json.get('car_number')
            money=request.json.get('money')
            paymoney,vip=is_money(car_number)
            query = Car_info.query_car_number_first(car_number)
            vip_query = Vip.query_car_number_vip(car_number)
            if query.car_state == 'False' or (vip_query is not None and (
                    vip_query.vip_month_card == 'True' or vip_query.vip_year_card == 'True')):
                data = {
                    'code': state_warn(),
                    'msg': '没有需要支付的金额',
                }
            else:
                if paymoney==int(money):
                    result = Car_info.modify_car_state(car_number, None, money)
                    order_number,time=order_num()  #获取订单编号以及订单创建时间
                    if result == 0:
                        Order.add_order(car_number,order_number,'车辆出库金额',time,money) #创建订单
                        Total.add_total(car_number, time, money, money)  # 添加总金额流水
                        data = {
                            'code': state_ok(),
                            'msg': '支付成功'
                        }
                    else:
                        data = {
                            'code': state_error(),
                            'msg': '支付失败'
                        }
                else:
                    data = {
                        'code': state_error(),
                        'msg': '支付金额不匹配,请重新刷新支付金额'
                    }
    return jsonify(data)

# 封装判断需要的金额的函数
def is_money(car_number):
    query = Car_info.query_car_number_first(car_number)
    car_leave_time = datetime.now() + timedelta(hours=10)  # 测试
    # car_leave_time = datetime.now()
    residence_time = car_leave_time - query.car_into_time
    minutes = int(residence_time.total_seconds() // 60)  # 计算停留的分钟数
    hours = minutes // 60  # 计算停留的小时数
    rut = Vip.query_car_number_is_vip(car_number)
    if rut == 0:
        money = 0
        vip='会员'
    else:
        vip='非会员'
        if minutes <= 30:
            money = 0  # 前三十分钟不收费
        elif hours <= 2:
            money = 5  # 前两小时收费 5 块钱
        else:
            money = 5 + (hours - 2) * 1  # 前两小时收费 5 块钱，之后每小时收费 1 块钱
    return money,vip

#封装产生订单编号函数
def order_num():
    time=datetime.now().strftime("%Y%m%d") #格式20230101
    order_end=str((Order.query_end_order()+1)).zfill(2) #新的订单id，补零
    order_id=time+order_end  #订单编号
    nowtime=datetime.now()
    return order_id,nowtime


# ------------------查询车牌对应的信息---------------------------
'''
功能:获取车牌对应的信息
用途：前台客户端
'''
@bp_car_info.route('/get/info', methods=['GET'])
def car_info_get_info():
    if request.method=='GET':
        car_number=request.args.get('car_number')
        place_info=Place.query_place_info(car_number)
        vip_info=Vip.query_car_number_card(car_number)
        if place_info:
            place_number=place_info.place_number
            car_state=place_info.car_state
        else:
            place_number=None
            car_state=None
        data={
            'code':state_ok(),
            'msg':'获取成功',
            'data':{
                'car_number':car_number,
                'place_number':place_number,
                'car_state':car_state,
                'is_vip':vip_info[0],
                'open_vip_time':vip_info[1],
                'past_vip':vip_info[2]
            }
        }
    return Response(json.dumps(data),mimetype='application/json')










